import { expect } from '@jest/globals';
import * as compressing from 'compressing';
import * as execa from 'execa';
import fs from 'fs-extra';
import JSON5 from 'json5';
import path from 'path';

import { initExecuteCommand, runHvigorAsync } from '../../common/common';
import {
  AbilityType,
  APIType,
  APIVersion,
  CaseLevel, compileApiNumber, compileVersion,
  CURRENT_HMOS_API,
  IsEnable,
  LanguageType,
  ModuleTemplateType,
  RuntimeOSType,
  sdkPathConvertMap,
  SDKType,
  SignType,
} from '../../plugins/project-builder/models/constants';
import { TestCaseBuilder } from '../../plugins/task-builder/task-case-builder';
import { ProjectBuildOption, TestCaseFun } from '../../plugins/task-builder/test-case';
import { TestTaskOption } from '../../plugins/task-builder/test-task-option';

const projectBuilderOption: ProjectBuildOption = {
  template: {
    sdk: SDKType.Single,
    runtimeOS: RuntimeOSType.HarmonyOS,
    apiVersion: CURRENT_HMOS_API,
    apiType: APIType.STAGE,
    language: LanguageType.ArkTs,
    abilityType: AbilityType.Application,
    entryTemplateType: ModuleTemplateType.EmptyAbility,
  },
};

const taskConfig: TestTaskOption = {
  caseLevel: CaseLevel.L1,
  sign: SignType.NoSign,
  ohpmInstall: IsEnable.DisAble,
};

const testFun: (module?: string) => TestCaseFun = (module?: string) => async (project, taskConfig, record) => {
  const projectRootPath = project.projectRootPath();
  const moduleStr = `${module}:default`;
  const commands = initExecuteCommand({
    mode: 'module',
    product: 'default',
    tasks: 'assembleHap',
    ...(module ? { module: `${module}@default` } : {}),
  });
  const result = await runHvigorAsync(projectRootPath, commands);
  record.addStep('执行hap编译构建', result);
  expect(result.stdout).toContain(`Finished :${moduleStr}@PackageHap`);
  expect(result.stdout).toContain('BUILD SUCCESSFUL');
  record.addStep('查看版本号', result);
  const sdkHome = process.env['DEVECO_SDK_HOME'];
  if (!sdkHome) {
    throw new Error("SDK Home env variable DEVECO_SDK_HOME doesn't exist");
  }
  const sdkName = sdkPathConvertMap[CURRENT_HMOS_API];
  if (!sdkName) {
    throw new Error(`Unknown sdk path from level ${CURRENT_HMOS_API}`);
  }
  const ts2abc = path.resolve(sdkHome, sdkName, 'openharmony/ets/build-tools/ets-loader/bin/ark/ts2abc.js');
  const apiNumber = compileApiNumber(projectBuilderOption.template.apiVersion, projectBuilderOption.template.runtimeOS);
  const arkVersion = await execa.node(ts2abc, ['--target-api-version',
    apiNumber.toString()]);

  // 将生成的hap包复制为zip包
  await fs.copyFile(
    path.resolve(projectRootPath, 'entry/build/default/outputs/default/entry-default-unsigned.hap'),
    path.resolve(projectRootPath, 'entry/build/default/outputs/default/entry-default-unsigned.zip'),
  );

  const hapPath = path.resolve(projectRootPath, 'entry/build/default/outputs/default/entry-default-unsigned');

  // 解压zip，解析出生成hap里的内容
  await compressing.zip.uncompress(
    path.resolve(projectRootPath, 'entry/build/default/outputs/default/entry-default-unsigned.zip'),
    path.resolve(projectRootPath, 'entry/build/default/outputs/default/entry-default-unsigned'),
  );

  // 判断是否含有.abc文件
  // eslint-disable-next-line max-len
  const files = await fs.readdir(path.resolve(projectRootPath, 'entry/build/default/outputs/default/entry-default-unsigned/ets'));
  const abcFiles = files.filter((file) => path.extname(String(file)) === '.abc');

  // 判断生成hap包里是否有.abc文件'
  expect(abcFiles.length > 0).toBe(true);

  // 读取文件
  fs.readFile(path.resolve(`${hapPath}/module.json`), (err, data) => {
    if (err) {
      throw err;
    }

    // 解析JSON5文件
    const obj = JSON5.parse(data.toString());
    const virtualMachine = obj.module.virtualMachine;

    // 判断module.json里面有virtualMachine:ark+版本号
    expect(`ark${arkVersion.stdout}` === virtualMachine).toBe(true);
  });
};
TestCaseBuilder.builder()
  .caseName('OPEN_LAB_AIDE_ZOS_BUILD_ARK_ETS_HOS_API10_STAGE_008')
  .description('新模型单模块stage-ets-cpp工程默认为ark构建')
  .projectBuilderOption(projectBuilderOption)
  .taskConfig(taskConfig)
  .testFun(testFun('entry'))
  .load();
